﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using PloobsEngine.Utils;
using XNAnimation;

namespace PloobsEngine.Modelo.Animation
{
    public class AnimatedModel : IAnimatedModel
    {
        public void Serialize(System.Xml.XmlTextWriter textWriter)
        {
            SerializerHelper.SerializeBaseType<string>(Name, "Name", textWriter);
        }
        public void DeSerialize(System.Xml.XmlNode node,EngineStuff engine)
        {
            Name = SerializerHelper.DeserializeBaseType<string>("Name", node);
            LoadModelo();

        }

        /// <summary>
        /// Serialization
        /// </summary>
        public AnimatedModel()
        {
        }

        String textureName = null;
        Texture2D texture = null;
        Texture2D bump = null;
        Texture2D specular = null;
        Texture2D glow = null;

        public AnimatedModel(String modelName)
        {
            this.ModelName = modelName;
            LoadModelo();
        }

        public AnimatedModel(String modelName,String diffuse)
        {
            this.ModelName = modelName;
            this.textureName = diffuse;
            LoadModelo();
        }

        private string _glowName = null;

        public string GlowName
        {
            get { return _glowName; }
            set { _glowName = value; }
        }

        private string _bumpName = null;

        public string BumpMapName
        {
            get { return _bumpName; }
            set { _bumpName = value; }
        }
        private string _specularName = null;

        public string SpecularMapName
        {
            get { return _specularName; }
            set { _specularName = value; }
        }

        public String DiffuseMapName
        {
            get { return textureName; }
            set { textureName = value; }
        }


        #region IModelo Members

        private String ModelName;
        private SkinnedModel skinnedModel;

        public void LoadModelo()
        {
            if (!String.IsNullOrEmpty(textureName))
            {
                this.texture = EngineStuff.CustomContentManager.GetAsset<Texture2D>(textureName);
            }
            if (!String.IsNullOrEmpty(_bumpName))
            {
                this.bump = EngineStuff.CustomContentManager.GetAsset<Texture2D>(_bumpName);
            }
            if (!String.IsNullOrEmpty(_specularName))
            {
                this.specular = EngineStuff.CustomContentManager.GetAsset<Texture2D>(_specularName);
            }
            if (!String.IsNullOrEmpty(_glowName))
            {
                this.glow = EngineStuff.CustomContentManager.GetAsset<Texture2D>(_glowName);
            }
            skinnedModel = EngineStuff.CustomContentManager.GetAsset<SkinnedModel>(ModelName);
            ModelBuilderHelper.Extract(skinnedModel.Model, out batchInformationS, out vertexBufferS, out indexBufferS);
        }


        #endregion

        #region IAnimatedModel Members

        public object GetAnimation()
        {
            return skinnedModel;
        }

        #endregion


        #region IModelo Members


        public string Name
        {
            get { return this.ModelName; }
            set { this.ModelName = value; }
        }

        #endregion

        #region IModelo Members

        ModelMesh[] mesh = null;
        public Microsoft.Xna.Framework.Graphics.ModelMesh[] getModelMeshes()
        {
            if (mesh == null)
            {
                mesh = new ModelMesh[skinnedModel.Model.Meshes.Count];
                skinnedModel.Model.Meshes.CopyTo(mesh, 0);
            }
            return mesh;

        }
        
        public Microsoft.Xna.Framework.Matrix[] getBonesTransformation()
        {
            Matrix[] m = new Matrix[skinnedModel.Model.Bones.Count];
            skinnedModel.Model.CopyAbsoluteBoneTransformsTo(m);
            return m;
        }

        
        #endregion

        #region IModelo Members


        public object getModelTag()
        {
            return skinnedModel.Model.Tag;
        }

        #endregion

        #region IModelo Members


        public Texture2D getTexture(TextureType type)
        {
            if (type == TextureType.DIFFUSE)
            {
                if (textureName != null)
                {
                    return this.texture;
                }
                else
                {
                    BasicEffect basiceffect = skinnedModel.Model.Meshes[0].Effects[0] as BasicEffect;
                    return basiceffect.Texture;
                }
            }
            else if (type == TextureType.BUMP)
            {
                return this.bump;
            }
            else if (type == TextureType.SPECULAR)
            {
                return this.specular;
            }
            else if (type == TextureType.GLOW)
            {
                return this.glow;
            }            
            else
            {
                return null;
            }
            
        }

        #endregion

        #region IModelo Members


        public BoundingSphere GetBoudingSphere()
        {
            BoundingSphere bs = new BoundingSphere();
            foreach (ModelMesh item in skinnedModel.Model.Meshes)
            {
              bs = BoundingSphere.CreateMerged(bs, item.BoundingSphere);
            }
            return bs;
        }

        BatchInformation[][] batchInformationS;
        VertexBuffer[] vertexBufferS;
        IndexBuffer[] indexBufferS;

        public int MeshNumber
        {
            get { return skinnedModel.Model.Meshes.Count; }
        }

        public VertexBuffer GetVertexBuffer(int meshNumber)
        {
            return vertexBufferS[meshNumber];
        }

        public IndexBuffer GetIndexBuffer(int meshNumber)
        {
            return indexBufferS[meshNumber];
        }

        public BatchInformation[] GetBatchInformation(int meshNumber)
        {
            return batchInformationS[meshNumber];
        }

        #endregion

        #region IModelo Members


        public int GetParentBoneIndex(int meshNumber)
        {
            return skinnedModel.Model.Meshes[meshNumber].ParentBone.Index;
        }

        #endregion
    }
}
